package com.symaster.common.swing.controller;

import com.symaster.common.swing.KeyStatus;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author yinmiao
 * @version 2022-11-21 15:19
 */
public class DragController {

    public static final int DRAG_TYPE_LEFT = 1;
    public static final int DRAG_TYPE_CENTER = 2;
    public static final int DRAG_TYPE_RIGHT = 3;
    private final Map<Integer, Set<DragListener>> listenerMap;
    private final Map<Integer, StartListener> startListenerMap;
    private final KeyStatus keyStatus;
    private Point lStart;
    private Point centerStart;
    private Point rStart;

    public DragController(KeyStatus keyStatus) {
        this.keyStatus = keyStatus;
        this.listenerMap = new HashMap<>();
        this.startListenerMap = new HashMap<>();
        initListener();
    }

    private void initListener() {
        keyStatus.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
            }

            @Override
            public void mousePressed(MouseEvent e) {
                if (1 == e.getButton()) {
                    lStart = e.getPoint();
                    if (startListenerMap.size() != 0) {
                        StartListener startListener = startListenerMap.get(DRAG_TYPE_LEFT);
                        if (startListener != null) {
                            lStart = startListener.handler(lStart);
                        }
                    }
                }
                if (2 == e.getButton()) {
                    centerStart = e.getPoint();
                    if (startListenerMap.size() != 0) {
                        StartListener startListener = startListenerMap.get(DRAG_TYPE_CENTER);
                        if (startListener != null) {
                            centerStart = startListener.handler(centerStart);
                        }
                    }
                }
                if (3 == e.getButton()) {
                    rStart = e.getPoint();
                    if (startListenerMap.size() != 0) {
                        StartListener startListener = startListenerMap.get(DRAG_TYPE_RIGHT);
                        if (startListener != null) {
                            rStart = startListener.handler(rStart);
                        }
                    }
                }
            }

            @Override
            public void mouseReleased(MouseEvent e) {

            }

            @Override
            public void mouseEntered(MouseEvent e) {

            }

            @Override
            public void mouseExited(MouseEvent e) {

            }
        });
        keyStatus.addMouseMotionListener(new MouseMotionListener() {
            @Override
            public void mouseDragged(MouseEvent e) {
                if (listenerMap.size() == 0) {
                    return;
                }
                if (keyStatus.leftMouseButtonPressed) {
                    Set<DragListener> dragListeners = listenerMap.get(DRAG_TYPE_LEFT);
                    if (dragListeners != null && dragListeners.size() != 0) {
                        for (DragListener dragListener : dragListeners) {
                            dragListener.handler(lStart, e.getPoint());
                        }
                    }
                    return;
                }
                if (keyStatus.centerMouseButtonPressed) {
                    Set<DragListener> dragListeners = listenerMap.get(DRAG_TYPE_CENTER);
                    if (dragListeners != null && dragListeners.size() != 0) {
                        for (DragListener dragListener : dragListeners) {
                            dragListener.handler(centerStart, e.getPoint());
                        }
                    }
                    return;
                }
                if (keyStatus.rightMouseButtonPressed) {
                    Set<DragListener> dragListeners = listenerMap.get(DRAG_TYPE_RIGHT);
                    if (dragListeners != null && dragListeners.size() != 0) {
                        for (DragListener dragListener : dragListeners) {
                            dragListener.handler(rStart, e.getPoint());
                        }
                    }
                }
            }

            @Override
            public void mouseMoved(MouseEvent e) {

            }
        });
    }

    public void setStartListener(int type, StartListener listener) {
        startListenerMap.put(type, listener);
    }

    public void addDragListener(int type, DragListener listener) {
        Set<DragListener> dragListeners = listenerMap.computeIfAbsent(type, k -> new HashSet<>());
        dragListeners.add(listener);
    }

    public interface StartListener {
        Point handler(Point point);
    }

    public interface DragListener {
        void handler(Point start, Point move);
    }
}
